import {Callout} from "nextra/components";
import { Tabs } from 'nextra/components';
import { Widget } from '@/components/demo/widget.tsx';
import LinkBadge from '@/components/ui/link-badge/link-badge.tsx';
import LinkBadgeGroup from '@/components/ui/link-badge/link-badge-group.tsx';

# Select Tile Group

A group of tiles that allow users to make a selection from a set of options.

<LinkBadgeGroup>
    <LinkBadge label="API Reference" href="https://pub.dev/documentation/forui/latest/forui.widgets.select_tile/"/>
</LinkBadgeGroup>

<Callout type="info">
    For desktop, a [select group](/docs/form/select-group) is generally recommended over this.
</Callout>

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-tile-group' variant='default' query={{}} height={300}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart copy
    enum Sidebar { recents, home, applications }

    FSelectTileGroup<Sidebar>(
      selectController: FSelectTileGroupController(values: {Sidebar.recents}),
      label: const Text('Sidebar'),
      description: const Text('These will be shown in the sidebar.'),
      children: [
        FSelectTile(
          title: const Text('Recents'),
          suffix: Icon(FIcons.timer),
          value: Sidebar.recents,
        ),
        FSelectTile(
          title: const Text('Home'),
          suffix: Icon(FIcons.house),
          value: Sidebar.home,
        ),
        FSelectTile(
          title: const Text('Applications'),
          suffix: Icon(FIcons.appWindowMac),
          value: Sidebar.applications,
        ),
      ],
    );
    ```

  </Tabs.Tab>
</Tabs>

## CLI

To generate and customize this style:

```shell copy
dart run forui style create select-tile-group
```

## Usage

### `FSelectTileGroup(...)`

```dart copy
FSelectTileGroup<Value>(
  selectController: FSelectTileGroupController(), // or FSelectTileGroupController.radio()
  scrollController: ScrollController(),
  style: FSelectMenuTileStyle(...),
  cacheExtent: 100,
  maxHeight: 200,
  dragStartBehavior: DragStartBehavior.start,
  physics: const ClampingScrollPhysics(),
  label: const Text('Sidebar'),
  description: const Text('Select the items you want to display in the sidebar.'),
  divider: FItemDivider.indented,
  onChange: (all) => print(all),
  onSelect: (selection) => print(selection),
  children: [
    FSelectTile(
      title: const Text('1'),
      value: Value.something,
    ),
  ],
);
```

### `FSelectTileGroup.builder(...)`

```dart copy
FSelectTileGroup<Value>.builder(
  selectController: FSelectTileGroupController(), // or FSelectTileGroupController.radio()
  scrollController: ScrollController(),
  style: FSelectMenuTileStyle(...),
  cacheExtent: 100,
  maxHeight: 200,
  dragStartBehavior: DragStartBehavior.start,
  physics: const ClampingScrollPhysics(),
  label: const Text('Settings'),
  description: const Text('Personalize your experience'),
  semanticsLabel: 'Settings',
  divider: FItemDivider.indented,
  onChange: (all) => print(all),
  onSelect: (selection) => print(selection),
  tileBuilder: (context, index) => index < 10 ? FSelectTile(
    title: Text('Tile $index'),
    value: Value.something,
  ) : null,
  count: 100,
);
```

## Examples

### Behavior

#### Scrollable

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-tile-group' variant='scrollable' query={{}} height={300}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart {5} copy
    FSelectTileGroup(
      selectController: FSelectTileGroupController(values: {Sidebar.recents}),
      label: const Text('Settings'),
      description: const Text('Personalize your experience'),
      maxHeight: 100,
      children: [
        FSelectTile(
          title: const Text('Recents'),
          suffix: Icon(FIcons.timer),
          value: Sidebar.recents,
        ),
        FSelectTile(
          title: const Text('Home'),
          suffix: Icon(FIcons.house),
          value: Sidebar.home,
        ),
        FSelectTile(
          title: const Text('Applications'),
          suffix: Icon(FIcons.appWindowMac),
          value: Sidebar.applications,
        ),
      ],
    );
    ```
  </Tabs.Tab>
</Tabs>

#### Lazy Scrollable

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-tile-group' variant='lazy' query={{}} height={300}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart copy
    FSelectTileGroup.builder(
      selectController: FSelectTileGroupController(values: {1}),
      label: const Text('Settings'),
      description: const Text('Personalize your experience'),
      maxHeight: 200,
      count: 200,
      tileBuilder:
          (context, index) => FSelectTile(title: Text('Tile $index'), suffix: Icon(FIcons.chevronRight), value: 1),
    );
    ```
  </Tabs.Tab>
</Tabs>

#### Multi-value Form

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-tile-group' variant='multi-value' query={{}} height={400}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart copy
    enum Language { dart, java, rust, python }

    class MultiValueForm extends StatefulWidget {
      const MultiValueForm();

      @override
      State<MultiValueForm> createState() => MultiValueFormState();
    }

    class MultiValueFormState extends State<MultiValueForm> {
      final _formKey = GlobalKey<FormState>();
      final controller = FSelectTileGroupController<Language>();

      @override
      Widget build(BuildContext context) => Form(
        key: _formKey,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            FSelectTileGroup(
              selectController: controller,
              label: const Text('Favorite Languages'),
              description: const Text('Your favorite language.'),
              validator: (values) => values?.isEmpty ?? true ? 'Please select at least one language.' : null,
              children: [
                FSelectTile(
                  title: const Text('Dart'),
                  value: Language.dart,
                ),
                FSelectTile(
                  title: const Text('Java'),
                  value: Language.java,
                ),
                FSelectTile(
                  title: const Text('Rust'),
                  value: Language.rust,
                ),
                FSelectTile(
                  title: const Text('Python'),
                  value: Language.python,
                ),
              ],
            ),
          ],
        ),
      );

      @override
      void dispose() {
        controller.dispose();
        super.dispose();
      }
    }
    ```

  </Tabs.Tab>
</Tabs>

#### Radio Form

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-tile-group' variant='radio' query={{}} height={400}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart copy
    enum Notification { all, direct, nothing }

    class RadioForm extends StatefulWidget {
      const RadioForm();

      @override
      State<RadioForm> createState() => RadioFormState();
    }

    class RadioFormState extends State<RadioForm> {
      final _formKey = GlobalKey<FormState>();
      final controller = FSelectTileGroupController<Notification>.radio();

      @override
      Widget build(BuildContext context) => Form(
        key: _formKey,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            FSelectTileGroup(
              selectController: controller,
              label: const Text('Notifications'),
              description: const Text('Select the notifications.'),
              validator: (values) => values?.isEmpty ?? true ? 'Please select a value.' : null,
              children: [
                FSelectTile(
                  title: const Text('All new messages'),
                  value: Notification.all,
                ),
                FSelectTile(
                  title: const Text('Direct messages and mentions'),
                  value: Notification.direct,
                ),
                FSelectTile(
                  title: const Text('Nothing'),
                  value: Notification.nothing,
                ),
              ],
            ),
            const SizedBox(height: 20),
            FButton(
              child: const Text('Save'),
              onPress: () {
                if (!_formKey.currentState!.validate()) {
                  // Handle errors here.
                  return;
                }

                _formKey.currentState!.save();
                // Do something.
              },
            ),
          ],
        ),
      );

      @override
      void dispose() {
        controller.dispose();
        super.dispose();
      }
    }
    ```

  </Tabs.Tab>
</Tabs>

### Appearance

#### Custom Icons

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-tile-group' variant='suffix' query={{}}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart {6, 11} copy
    FSelectTileGroup(
      selectController: FSelectTileGroupController.radio(),
      label: const Text('Settings'),
      children: [
        FSelectTile.suffix(
          prefix: Icon(FIcons.list),
          title: const Text('List View'),
          value: 'List',
        ),
        FSelectTile.suffix(
          prefix: Icon(FIcons.layoutGrid),
          title: const Text('Grid View'),
          value: 'Grid',
        ),
      ],
    );
    ```
  </Tabs.Tab>
</Tabs>

#### Full Divider

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-tile-group' variant='default' query={{divider: 'full'}} height={300}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart {5} copy
    enum Sidebar { recents, home, applications }

    FSelectTileGroup<Sidebar>(
      selectController: FSelectTileGroupController(values: {Sidebar.recents}),
      divider: FItemDivider.full,
      label: const Text('Sidebar'),
      description: const Text('These will be shown in the sidebar.'),
      children: [
        FSelectTile(
          title: const Text('Recents'),
          suffix: Icon(FIcons.timer),
          value: Sidebar.recents,
        ),
        FSelectTile(
          title: const Text('Home'),
          suffix: Icon(FIcons.house),
          value: Sidebar.home,
        ),
        FSelectTile(
          title: const Text('Applications'),
          suffix: Icon(FIcons.appWindowMac),
          value: Sidebar.applications,
        ),
      ],
    );
    ```

  </Tabs.Tab>
</Tabs>

#### No Divider

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-tile-group' variant='default' query={{divider: 'none'}} height={300}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart {5} copy
    enum Sidebar { recents, home, applications }

    FSelectTileGroup<Sidebar>(
      selectController: FSelectTileGroupController(values: {Sidebar.recents}),
      divider: FItemDivider.none,
      label: const Text('Sidebar'),
      description: const Text('These will be shown in the sidebar.'),
      children: [
        FSelectTile(
          title: const Text('Recents'),
          suffix: Icon(FIcons.timer),
          value: Sidebar.recents,
        ),
        FSelectTile(
          title: const Text('Home'),
          suffix: Icon(FIcons.house),
          value: Sidebar.home,
        ),
        FSelectTile(
          title: const Text('Applications'),
          suffix: Icon(FIcons.appWindowMac),
          value: Sidebar.applications,
        ),
      ],
    );
    ```

  </Tabs.Tab>
</Tabs>
